package modelo.geografia;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import modelo.ExceptionDatosFaltantes;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Mapa {

	private List<Capital> capitales;
	
	//Implementacion singleton
	
	private Mapa() {
		this.capitales = new ArrayList<Capital>();
	}
	
	/* No parece ser necesario
	private Mapa(String nombreXML) throws Exception{
		
		this.capitales = new ArrayList<Capital>();
		this.cargarCapitalesDesdeXML(nombreXML);
		
	}
	*/
	private static Mapa unicaInstancia = null;
	
	//Nota: Al ser un singleton, las pruebas fallan porque se mantiene el estado. Se agrega la posibilidad
	//de vaciar el mapa provisoriamente, mientras buscamos una mejor solucion.
	
	private static boolean mapaVacio = true;
	
	public static Mapa obtenerMapa() {
		if( (unicaInstancia == null) || mapaVacio )
		{
			unicaInstancia = new Mapa();
			mapaVacio = false;
		}
		return unicaInstancia;
	}
	
	public static void cargarMapa(String nombreXML) throws Exception {
		File file = new File(nombreXML);
		if(!file.exists())
			throw new ExceptionDatosFaltantes("No se encuentra el archivo de Mapa, se finalizara la aplicacion");
		obtenerMapa().cargarCapitalesDesdeXML(nombreXML);
	}
	
	public void agregarCapital(Capital unaCapital) {
		
		this.capitales.add(unaCapital);
		
	}

	public int cantidadDeCapitales() {
		
		return ( capitales.size() );
	}
	
	public boolean contieneA(Capital unaCapital){
		
		return (capitales.contains(unaCapital));
	}
	
	public List<Capital> getCapitales(){
		
		return this.capitales;
		
	}
	
	public void cargarCapitalesDesdeXML(String nombreXML) throws Exception{
		
		File archivo = new File(nombreXML);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(archivo);
		doc.getDocumentElement().normalize();
		
		Element elementoCapitales = (Element) doc.getElementsByTagName("Capitales").item(0);
		
		Capital capitalNueva;
		for (int i = 0 ; i < elementoCapitales.getChildNodes().getLength() ; i++ ){
			
			/*Coordenada coord = new Coordenada(Integer.parseInt(elementoCapitales.getChildNodes().item(i).getChildNodes().item(0).getAttributes().item(0).getNodeValue()) ,
					Integer.parseInt(elementoCapitales.getChildNodes().item(i).getChildNodes().item(0).getAttributes().item(1).getNodeValue()));
			Capital capitalNueva = new Capital(elementoCapitales.getChildNodes().item(i).getAttributes().item(0).getNodeValue() , coord);
			
			capitalNueva.agregarEstablecimiento(new EstablecimientoCultural("Aeropuerto"));
			capitalNueva.agregarEstablecimiento(new EstablecimientoEconomico("Banco"));
			capitalNueva.agregarEstablecimiento(new EstablecimientoHistorico("Museo"));*/
			capitalNueva = Capital.hidratar((Element)elementoCapitales.getChildNodes().item(i));
			
			unicaInstancia.agregarCapital(capitalNueva);
		}
		
		unicaInstancia.conectarCapitales();
	}

	private void conectarCapitales() throws Exception {
		
		for (int i = 0 ; i < (this.capitales.size() - 2) ; i ++){
			
			this.capitales.get(i).conectarCapital( this.capitales.get( i+1 ) );
			this.capitales.get(i).conectarCapital( this.capitales.get( i+2 ) );
		}
		//this.capitales.get( this.cantidadDeCapitales() -2 ) .conectarCapital( this.capitales.get( this.capitales.size() -1 ) );
		this.capitales.get( this.cantidadDeCapitales() -2 ) .conectarCapital( this.capitales.get( 0 ) );
		this.capitales.get( this.cantidadDeCapitales() -1 ) .conectarCapital( this.capitales.get( 0 ) );
		this.capitales.get( this.cantidadDeCapitales() -1 ) .conectarCapital( this.capitales.get( 1 ) );
		
	}

	public Capital obtenerCapitalLlamada(String nombre) throws Exception {
		
		Capital capitalEncontrada = null;
		boolean esta = false;
		for (int i = 0 ; i < capitales.size() && !esta  ; i ++ ){
			
			
			if ( capitales.get(i).getNombre().equals(nombre)){
				capitalEncontrada = capitales.get(i);
				esta = true;
			}
		}
		if (esta)
			return capitalEncontrada;
		else
			return null;
	}

	public static void vaciar() {
		
		mapaVacio = true;
		
	}

	public static void reiniciar() {
		Mapa mapa = Mapa.obtenerMapa();
		List<Capital> capitales = mapa.getCapitales();
		 
		for(Capital capital : capitales)
		{
			capital.reiniciar();
			
		}
	}
	
	/* No parece ser necesario
	 * 
	public Node serializar(Document doc) {
		
		Element elementoMapa = doc.createElement("Mapa");
		
		Element elementoCapitales = doc.createElement("Capitales");
		
		for( Capital capital : this.capitales ){
			elementoCapitales.appendChild(capital.serializar(doc));
		}
		
		elementoMapa.appendChild(elementoCapitales);
		
		return elementoMapa;
	}
	 */
	
}
